<script setup lang="ts">
import Node from "./base/Node.vue";
import { ElMessage } from "element-plus";
import { reloadNodeId } from "@/utils/process";
import nodeMixin from "../NodeMixin";
import type { FlowModelNode } from "../ProcessDef";
import nodeType, { NodeComponents } from "../ProcessNodes";
import { deepCopy } from "@/utils/process";
import { onMounted, ref } from "vue";

const props = defineProps({
  ...nodeMixin.props
});

const emit = defineEmits(["insertNode", "delete", "select"]);
const _value = defineModel<FlowModelNode>();
const nodeRef = ref();
const mounted = ref(false);

onMounted(() => {
  mounted.value = true;
});

/**
 * 插入节点
 * @param branch 该节点要插入的支路（节点数组）
 * @param i 插入哪个元素后面的索引，实际插入位置为i+1
 * @param type 要插入的节点类型
 */
function insertNode(branch, i, type) {
  if (nodeType[type]) {
    branch.splice(i + 1, 0, nodeType[type].create());
  } else {
    ElMessage.warning("请在ProcessNodes.js内配置该节点");
  }
}

/**
 * 删除某个元素
 * @param branch 要删除的元素所在支路
 * @param i 删除的元素在该支路内索引位置
 */
function deleteNode(branch, i) {
  branch.splice(i, 1);
}

//添加网关分支
function addBranch() {
  const index = _value.value.branch.length - 1;
  const type = _value.value.props.type;
  if (nodeType[type]) {
    _value.value.props.branch.splice(index, 0, nodeType[type].createBranch(index + 1));
    _value.value.branch.splice(index, 0, []);
  } else {
    ElMessage.warning("请在ProcessNodes.js内配置该节点");
  }
}

//复制一个分支
function copyBranch(i) {
  //复制条件
  const cd = deepCopy(_value.value.props.branch[i]);
  cd.name = cd.name + "-copy";
  //复制整个分支
  const bh = deepCopy(_value.value.branch[i]);
  //重载节点id
  reloadNodeId(cd);
  reloadNodeId(bh);
  //插入到新位置
  _value.value.props.branch.splice(i + 1, 0, cd);
  _value.value.branch.splice(i + 1, 0, bh);
}

//删除网关分支
function deleteBranch(i) {
  if (_value.value.branch.length <= 2) {
    //只有两个分支，那么就直接删除整个网关
    emit("delete", props.branch, props.index);
  } else {
    //直接删除此分支
    _value.value.props.branch.splice(i, 1);
    _value.value.branch.splice(i, 1);
  }
}

//左移分支
function moveL(i) {
  exchange(_value.value.props.branch, i, i - 1);
  exchange(_value.value.branch, i, i - 1);
}

//右移分支
function moveR(i) {
  exchange(_value.value.props.branch, i, i + 1);
  exchange(_value.value.branch, i, i + 1);
}

//交换数组俩元素位置
function exchange(arr, si, ti) {
  const temp = arr[si];
  arr[si] = arr[ti];
  arr[ti] = temp;
}

function select(nd, i) {
  if (!(i === _value.value.branch.length - 1 && _value.value.props.type !== "Parallel")) {
    emit("select", { node: _value.value.props.branch[i], taskIndex: i });
  }
}

function validate(errs) {
  const branch = _value.value.branch;
  const prop = _value.value.props;
  branch.forEach((item, index) => {
    if (item.length < 1) {
      errs.push(
        `${prop.type === "Serial" ? "串行网关" : "并行网关"} ${_value.value.name}的${prop.branch[index].name}分支未添加任务节点`
      );
    }
  });
  if (Array.isArray(nodeRef.value)) {
    nodeRef.value.forEach(ref => {
      if (ref.validate) {
        ref.validate(errs);
      }
    });
  } else if (nodeRef.value && nodeRef.value.validate) {
    nodeRef.value.validate(errs);
  }
}

defineExpose({ validate });
</script>

<template>
  <div class="w-p-gateway">
    <div class="w-p-branch">
      <el-button class="w-p-gateway-add" round plain v-if="!readonly" @click="addBranch"
        >添加分支</el-button
      >
      <!--分支遍历-->
      <div
        v-for="(nodes, i) in modelValue.branch"
        :key="i + '_br'"
        :class="{
          'w-p-branch-item': true,
          'w-p-branch-item-l': i === 0,
          'w-p-branch-item-r': i === modelValue.branch.length - 1
        }"
      >
        <div v-if="mounted">
          <!--构造分支头节点-->
          <component
            ref="nodeRef"
            :readonly="readonly"
            v-model="modelValue.props.branch[i]"
            :index="i"
            :moveRn="i < modelValue.branch.length - (modelValue.props.type !== 'Parallel' ? 2 : 1)"
            :moveLn="i > 0"
            :is="NodeComponents[modelValue.props.type]"
            :isDefault="i === modelValue.branch.length - 1 && modelValue.props.type !== 'Parallel'"
            @insertNode="type => insertNode(nodes, -1, type)"
            @delete="deleteBranch(i)"
            @copy="copyBranch(i)"
            @move-l="moveL(i)"
            @move-r="moveR(i)"
            @select="nd => select(nd, i)"
          />
          <!--渲染分支-->
          <template v-for="(node, bi) in nodes" :key="bi + '_bi'">
            <!--分支里面继续遍历-->
            <component
              ref="nodeRef"
              :readonly="readonly"
              v-model="modelValue.branch[i][bi]"
              :is="NodeComponents[node.type]"
              :branch="nodes"
              :index="bi"
              :only-job="true"
              :flowHistory="flowHistory"
              @insertNode="insertNode"
              @delete="deleteNode(nodes, bi)"
              @select="nd => emit('select', nd)"
            />
          </template>
        </div>
      </div>
    </div>
    <node
      :readonly="readonly"
      :class="{ 'w-p-branch-end': branch.length === index + 1 }"
      :show-body="false"
      :only-job="true"
      @insertNode="type => $emit('insertNode', branch, index, type)"
    />
  </div>
</template>

<style scoped lang="scss">
.w-p-gateway {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;

  .w-p-gateway-add {
    position: absolute;
    top: -16px;
    z-index: 2;
  }
}

.w-p-branch {
  position: relative;
  display: flex;
  justify-content: center;
  background: $main-bgc;

  //再画一个横线连接所有支路
  &:before {
    position: absolute;
    width: calc(100% - $node-width);
    height: $node-line-width;
    content: "";
    background: $node-line-color;
  }

  &:after {
    position: absolute;
    bottom: 0;
    width: calc(100% - $node-width);
    height: $node-line-width;
    content: "";
    background: $node-line-color;
  }

  .w-p-branch-item {
    position: relative;
    display: flex;
    justify-content: center;
    padding: 0 60px;

    & > div {
      z-index: 1; //防止连线跑到它上面
      display: flex;
      flex-direction: column;
      align-items: center;
      margin-top: 40px;

      & > .w-p-node:last-child {
        :deep(.w-p-node-add) {
          //分支最后一个节点要去除箭头，影响美观
          &:after {
            display: none !important;
          }
        }
      }
    }

    &:before {
      position: absolute;
      width: $node-line-width;
      height: 100%;
      content: "";
      background: $node-line-color;
    }
  }

  .w-p-branch-item-l,
  .w-p-branch-item-r {
    &:after {
      position: absolute;
      top: 0;
      width: 50%;
      height: $node-line-width;
      //当分支不是偶数时，需要一个遮罩线
      content: "";
      background: $main-bgc;
    }

    & > div {
      &:before {
        position: absolute;
        bottom: 0;
        width: 50%;
        height: $node-line-width;
        //当分支不是偶数时，需要一个遮罩线
        content: "";
        background: $main-bgc;
      }
    }
  }

  :deep(.w-p-branch-end .w-p-node-add) {
    &:after {
      border: none;
    }
  }

  .w-p-branch-item-l {
    margin-left: 0;

    & > div {
      &:before {
        left: -1px;
      }
    }

    &:after {
      left: -1px;
    }
  }

  .w-p-branch-item-r {
    margin-right: 0;

    & > div {
      &:before {
        right: -1px;
      }
    }

    &:after {
      right: -1px;
    }
  }
}
</style>
